package gov.pbc.nn.uflo.view;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Component;

import com.bstek.bdf2.core.business.IDept;
import com.bstek.bdf2.core.context.ContextHolder;
import com.bstek.dorado.annotation.DataProvider;
import com.bstek.dorado.data.entity.EntityUtils;
import com.bstek.uflo.model.HistoryProcessInstance;
import com.bstek.uflo.model.HistoryTask;
import com.bstek.uflo.model.ProcessInstance;
import com.bstek.uflo.model.ProcessInstanceState;
import com.bstek.uflo.model.task.Task;
import com.bstek.uflo.query.HistoryTaskQuery;
import com.bstek.uflo.query.ProcessInstanceQuery;
import com.bstek.uflo.query.TaskQuery;
import com.bstek.uflo.service.HistoryService;
import com.bstek.uflo.service.ProcessService;
import com.bstek.uflo.service.TaskService;

import gov.pbc.nn.core.bdf.entity.Dept;
import gov.pbc.nn.core.bdf.service.DeptService.DefaultDeptRowMapper;
import gov.pbc.nn.core.dao.PbcnnCoreJdbcDao;
import gov.pbc.nn.uflo.UfloUtils;
import gov.pbc.nn.uflo.entity.Opinion;

@Component
public class ProcessStepPR {

	@Autowired
	@Qualifier("uflo.processService")
	private ProcessService processService;
	@Autowired
	@Qualifier("uflo.taskService")
	private TaskService taskService;
	@Autowired
	@Qualifier("uflo.historyService")
	private HistoryService historyService;
	@Resource(name = PbcnnCoreJdbcDao.BEAN_ID)
	private PbcnnCoreJdbcDao jdbcDao;

	@DataProvider
	public List<ProcessInstance> loadTopProcessInstance(String businessId) throws Exception {
		String sql = "SELECT DISTINCT\n" + "	pi.*,u.CNAME_ as PROMOTER_CNAME_\n" + "FROM\n" + "	uflo_process_instance pi\n" + "INNER JOIN uflo_process p ON pi.PROCESS_ID_ = p.ID_\n"
				+ "LEFT JOIN t_user u on u.USERNAME_=pi.PROMOTER_\n" + "WHERE\n" + "	pi.BUSINESS_ID_ =?\n" + "AND pi.PARENT_ID_ = 0";

		List<ProcessInstance> list = this.jdbcDao.getJdbcTemplate().query(sql, new Object[] { businessId }, new RowMapper<ProcessInstance>() {

			@Override
			public ProcessInstance mapRow(ResultSet rs, int rowNum) throws SQLException {
				ProcessInstance pi = new ProcessInstance();
				pi.setBusinessId(rs.getString("BUSINESS_ID_"));
				pi.setCreateDate(rs.getTimestamp("CREATE_DATE_"));
				pi.setCurrentNode(rs.getString("CURRENT_NODE_"));
				pi.setCurrentTask(rs.getString("CURRENT_TASK_"));
				pi.setHistoryProcessInstanceId(rs.getLong("HIS_PROCESS_INSTANCE_ID_"));
				pi.setId(rs.getLong("ID_"));
				pi.setParallelInstanceCount(rs.getInt("PARALLEL_INSTANCE_COUNT_"));
				pi.setParentId(rs.getLong("PARENT_ID_"));
				pi.setProcessId(rs.getLong("PROCESS_ID_"));
				pi.setPromoter(rs.getString("PROMOTER_"));
				pi.setRootId(rs.getLong("ROOT_ID_"));
				pi.setState(ProcessInstanceState.valueOf(rs.getString("STATE_")));
				pi.setTag(rs.getString("TAG_"));
				try {
					pi = EntityUtils.toEntity(pi);
					EntityUtils.setValue(pi, "promoterCname", rs.getString("PROMOTER_CNAME_"));
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				return pi;
			}

		});
		return list;
	}

	@DataProvider
	public List<ProcessInstance> loadProcessInstanceByParentId(long parentId) throws Exception {
		ProcessInstanceQuery query = this.processService.createProcessInstanceQuery();
		query.parentId(parentId);
		return (List) query.list();
	}

	@DataProvider
	public List<Task> loadTasks(long processInstanceId) {
		TaskQuery query = this.taskService.createTaskQuery();
		query.processInstanceId(processInstanceId);
		return (List) query.list();
	}

	@DataProvider
	public String getUserCname(String username) {
		if (StringUtils.isEmpty(username)) {
			return null;
		}
		String sql = "select CNAME_ from t_USER where username_=?";
		List<Map<String, Object>> list = this.jdbcDao.getJdbcTemplate().queryForList(sql, username);
		return (String) (list.isEmpty() ? null : (list.get(0).get("CNAME_")));
	}

	@DataProvider
	public  String getDeptName(String username) {
		String sql = "SELECT\n" + " d.*\n" + " FROM\n" + " t_dept d\n" + " INNER JOIN bdf2_user_dept ud ON d.ID_ = ud.DEPT_ID_\n" + " WHERE\n" + " ud.USERNAME_ = ?";
		PbcnnCoreJdbcDao jdbc = ContextHolder.getBean(PbcnnCoreJdbcDao.BEAN_ID);
		List<IDept> depts = jdbc.getJdbcTemplate().query(sql, new String[] { username }, new DefaultDeptRowMapper());
		if (depts.isEmpty()) {
			return null;
		}
		return depts.get(0).getName();
	}

	@DataProvider
	public List<HistoryProcessInstance> loadHistoryProcessInstance(String businessId) {
		String sql = "SELECT DISTINCT\n" + "	pi.*, u.CNAME_ AS promoter_cname_\n" + "FROM\n" + "	uflo_his_process_instance pi\n" + "INNER JOIN uflo_process p ON pi.PROCESS_ID_ = p.ID_\n"
				+ "LEFT JOIN t_user u ON u.USERNAME_ = pi.PROMOTER_\n" + "WHERE\n" + "	pi.BUSINESS_ID_ =?\n" +
				// "AND pi.PROCESS_INSTANCE_ID_ =?\n" +
				// "AND pi.PROCESS_ID_ =?\n" +
				"order by pi.CREATE_DATE_";
		List<HistoryProcessInstance> list = this.jdbcDao.getJdbcTemplate().query(sql, new Object[] { businessId /*
																												 * ,
																												 * processInstanceId
																												 * ,
																												 * processId
																												 */}, new RowMapper<HistoryProcessInstance>() {

			@Override
			public HistoryProcessInstance mapRow(ResultSet rs, int rowNum) throws SQLException {
				HistoryProcessInstance pi = new HistoryProcessInstance();
				pi.setBusinessId(rs.getString("BUSINESS_ID_"));
				pi.setCreateDate(rs.getTimestamp("CREATE_DATE_"));
				pi.setEndDate(rs.getTimestamp("END_DATE_"));
				pi.setId(rs.getLong("ID_"));
				pi.setProcessId(rs.getLong("PROCESS_ID_"));
				pi.setProcessInstanceId(rs.getLong("PROCESS_INSTANCE_ID_"));
				pi.setPromoter(rs.getString("PROMOTER_"));
				pi.setTag(rs.getString("TAG_"));
				try {
					pi = EntityUtils.toEntity(pi);
					EntityUtils.setValue(pi, "promoterCname", rs.getString("PROMOTER_CNAME_"));
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				return pi;
			}

		});
		return list;
	}

	@DataProvider
	public List<HistoryTask> loadHistoryTasks(long historyProcessInstanceId) {
		HistoryTaskQuery historyTaskQuery = this.historyService.createHistoryTaskQuery();
		historyTaskQuery.historyProcessInstanceId(historyProcessInstanceId);
		historyTaskQuery.addOrderDesc("endDate");
		return (List) historyTaskQuery.list();
	}

	@DataProvider
	public String getOpinion(String businessId, long processInstanceId, long taskId, String assignee) {
		List<String> users = new ArrayList<String>();
		if (StringUtils.isNotBlank(assignee)) {
			users.add(assignee);
		}
		List<Opinion> list = UfloUtils.getLatestOpinions(processInstanceId, businessId, null, taskId, users);
		if (list.isEmpty()) {
			return null;
		} else {
			return list.get(0).getOpinion();
		}
	}
}
